package com.cy.pj.sys.service;

import java.util.HashSet;
import java.util.List;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.cy.pj.sys.dao.SysUserDao;
import com.cy.pj.sys.dao.SysUserRoleDao;
import com.cy.pj.sys.pojo.SysUser;

//@Component	
public class ShiroUserRealm extends AuthorizingRealm {
	@Autowired
	SysUserDao sysUserDao;
	@Autowired
	SysUserRoleDao userRoleDao;
	/**
	 * 负责授权信息的封装
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		//获取用户的id
		SysUser sysUser = (SysUser)principals.getPrimaryPrincipal();
		Integer id = sysUser.getId();
		//查询数据库中对应的菜单信息
		List<String> list = userRoleDao.findPermissionByUserId(id);
		if(list==null||list.size()==0) {
			throw new AuthorizationException();
		}
		//转为set集合并进行去除空数据
		HashSet<String> roles = new HashSet<>();
		for (String str : list) {
			if(!StringUtils.isEmpty(str)) {
				roles.add(str);
			}
		}
		//进行封装回传
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		info.setStringPermissions(roles);
		System.out.println("访问授权!!!");
		return info;
	}

	/**
	 * 通过此方法完成认证数据的获取及封装,系统底层会将认证数据传递认证管理器,由认证管理器完成认证工作
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		UsernamePasswordToken uToken = (UsernamePasswordToken) token;
		//获取用户输入的用户名
		String username = uToken.getUsername();
		//通过用户名从数据库查找对象
		SysUser sysUser = sysUserDao.findUserByUsername(username);
		//判断是否存在此用户
		if(sysUser==null) throw new UnknownAccountException();
		//判断用户是否被禁用
		if(sysUser.getValid()==0) throw new LockedAccountException();
		//封装用户信息构建AuthenticationInfo返回值对象
		ByteSource credentialsSalt = ByteSource.Util.bytes(sysUser.getSalt());
		AuthenticationInfo info = new SimpleAuthenticationInfo(
				sysUser,//身份,一般为查询到的对象的poojo类
				sysUser.getPassword(),//加密的密码 
				credentialsSalt, 
				getName());
		return info;
	}
	
	/** 设置凭证匹配器,加密方式要与密码的加密算法相同 */
	@Override
	public CredentialsMatcher getCredentialsMatcher() {
		//创建加密对象
		HashedCredentialsMatcher cManager = new HashedCredentialsMatcher(); 
		//设置加密算法
		cManager.setHashAlgorithmName("MD5");
		//设置加密次数
		cManager.setHashIterations(1);
		return cManager;
	}

}
